<script setup lang="ts">
import {
  type FormInst,
  NButton,
  NSelect,
  NFormItem,
  type SelectOption,
  NInput,
  useMessage,
  NImage,
  NSpace,
  NForm,
  NInputNumber,
  NDataTable,
  type FormItemRule,
  type DataTableColumns,
  type UploadFileInfo
} from 'naive-ui'
import { ref, shallowRef, watch, type Ref, onMounted } from 'vue'
import FixedAction from '@/components/FixedAction.vue'
import useRouteReplace from '@/hooks/useRouteReplace'
import { useRoute } from 'vue-router'
import type { CTSelectOption } from '@/api/collection'
import type { BatchItemDetailModel } from '@/api/batchV2'
import { sendRequest } from '@/utils/api'
import type { HttpResponse } from '@/utils/http'
import VBackImg from '@/assets/images/back.png'
import { keysOf } from '@/utils/object'
import VAttachments from '@/views/OA/Common/Attachments.vue'
import useRouteParam from '@/hooks/useRouteParam'
// import VUploader from '@/components/VUploaderV3/VUploader.vue'
// import type { CustomFile } from '@/components/VUploaderV3/types'
import FUploader from './FUploader.vue'

const message = useMessage()
const route = useRoute()
const routeReplace = useRouteReplace(route.query.redirect as string)
const isUpdate = route.query.type === 'u'
const isDetail = route.query.type === 'r'
const isAdd = route.query.type === 'c'
const isTF = route.query.isTF === 'true'
const fromRegisteredDetail = route.query.fromRegisteredDetail === 'true'

const formInst = ref<FormInst | null>(null)

const createQuerySelectOptions = (
  options: Ref<CTSelectOption[]>,
  loading: Ref<boolean>,
  onFinish?: () => void
) => {
  return async (parentCode?: string) => {
    try {
      loading.value = true
      const [error, res] = await sendRequest<HttpResponse<CTSelectOption[]>>({
        module: 'collection',
        api: 'typeSelectByCode',
        override: {
          params: {
            parentCode: parentCode || null
          }
        }
      })
      if (error) throw error
      if (res.code !== 0) throw new Error(res.msg)
      options.value = res.data
      onFinish?.()
    } catch (error) {
      console.log(error)
    } finally {
      loading.value = false
    }
  }
}
const createAutoSelectFirstItem = (value: Ref<string | null>, options: Ref<CTSelectOption[]>) => {
  return () => {
    if (options.value.length > 0) {
      value.value = options.value[0].value
    }
  }
}
const createCascader = (
  configs: {
    value: Ref<string | null>
    options: Ref<CTSelectOption[]>
    loading: Ref<boolean>
    autoSelectFirst: boolean
    onFinish?: () => void
  }[]
) => {
  const queryFuncList = configs.map((config) => {
    const autoSelect = config.autoSelectFirst
      ? createAutoSelectFirstItem(config.value, config.options)
      : undefined
    return createQuerySelectOptions(config.options, config.loading, () => {
      autoSelect?.()
      config.onFinish?.()
    })
  })

  for (let i = 0; i < configs.length - 1; i++) {
    if (!configs[i + 1]) continue

    let flag = false
    watch(
      configs[i].value,
      (v) => {
        if (isUpdate && !flag && v) {
          flag = true
        } else {
          configs[i + 1].options.value = []
          configs[i + 1].value.value = null
        }

        if (!v) return
        queryFuncList[i + 1](v)
      },
      { immediate: true }
    )
  }

  return queryFuncList[0]
}

const oneSelectValue = ref<string | null>(null)
const oneSelectOptions = shallowRef<CTSelectOption[]>([])
const oneSelectLoading = ref(false)

const twoSelectValue = ref<string | null>(null)
const twoSelectOptions = shallowRef<CTSelectOption[]>([])
const twoSelectLoading = ref(false)

const threeSelectValue = ref<string | null>(null)
const threeSelectOptions = shallowRef<CTSelectOption[]>([])
const threeSelectLoading = ref(false)

const isUseLastSelect = ref(false)
const cascader = createCascader([
  {
    value: oneSelectValue,
    options: oneSelectOptions,
    loading: oneSelectLoading,
    autoSelectFirst: false
  },
  {
    value: twoSelectValue,
    options: twoSelectOptions,
    loading: twoSelectLoading,
    autoSelectFirst: false
  },
  {
    value: threeSelectValue,
    options: threeSelectOptions,
    loading: threeSelectLoading,
    autoSelectFirst: false,
    onFinish: () => (isUseLastSelect.value = threeSelectOptions.value.length > 0)
  }
])

const isTrue = ref(false)
const changeTree = (v: string) => {
  formData.value.collectTypeCode = v
  if (formData.value.collectTypeCode === 'A3007') {
    isTrue.value = true
  } else {
    isTrue.value = false
  }
}

interface FormData {
  appearance: string | null
  batchId: number | null
  binding: string | null
  clueId: number | null
  clueItemId: number | null
  collectTypeCode: string | null
  createdTime: string | null
  deliveryUnit: string | null
  depositTerm: string | null
  endDate: string | null
  fileIds: string | null
  id: number | null
  imgIds: string | null
  itemCode: string | null
  itemName: string
  itemNum: number
  itemTypeName: string | null
  itemTypeCode: string
  language: string | null
  materialQuality: string | null
  notes: string | null
  press: string | null
  receiveTime: string | null
  receiveUser: string | null
  specifications: string | null
  startDate: string | null
  supervisor: string | null
  transferUser: string | null
  transferUserPhone: string | null
  updatedTime: string | null
  years: string | null
}
const formData = ref({} as FormData)

const imageFileList = ref<UploadFileInfo[]>([])

const validatorTypeFormItem = () => {
  // if (isUseLastSelect.value) return threeSelectValue.value !== null
  // return twoSelectValue.value !== null
  return oneSelectValue.value !== null
}

const submitLoading = ref(false)
const handleSubmit = () => {
  if (submitLoading.value) return

  formInst.value?.validate(async (err) => {
    if (err) return
    submitLoading.value = true

    try {
      const [error, res] = await sendRequest<HttpResponse>({
        module: 'batchV2',
        api: 'saveOrUpdateBatchItem',
        override: {
          data: {
            ...formData.value,
            batchId: route.params.id,
            itemTypeName: isUseLastSelect.value
              ? threeSelectOptions.value.find((item) => item.value === threeSelectValue.value)
                  ?.label
              : twoSelectValue.value
              ? twoSelectOptions.value.find((item) => item.value === twoSelectValue.value)?.label
              : oneSelectOptions.value.find((item) => item.value === oneSelectValue.value)?.label,
            itemTypeCode: isUseLastSelect.value
              ? threeSelectValue.value
              : twoSelectValue.value
              ? twoSelectValue.value
              : oneSelectValue.value,
            imgIds: imageFileList.value
              ? // @ts-ignore
                imageFileList.value.map((e) => e.file?.remoteId).join(',')
              : null
          }
        }
      })
      if (error) throw error
      if (res.code !== 0) throw new Error(res.msg)
      message.success(res.msg)
      window.flags.flushEditBatchTable = true
      routeReplace()
    } catch (error) {
      if (!(error instanceof Error)) return
      message.error(error.message)
    } finally {
      submitLoading.value = false
    }
  })
}

const clueInfo = ref({} as BatchItemDetailModel)
const checkIsDetail = async () => {
  if (!isDetail && !isUpdate) return

  try {
    const [error, res] = await sendRequest<HttpResponse<BatchItemDetailModel>>({
      module: 'batchV2',
      api: 'batchItemDetail',
      uri: {
        id: route.params.itemId as string
      }
    })
    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)

    const { data } = res
    changeTree(data.collectTypeCode)

    if (data.fullCode) {
      const tmp = data.fullCode.split('>')
      if (tmp.length == 1) {
        oneSelectValue.value = tmp[0]
      } else if (tmp.length == 2) {
        oneSelectValue.value = tmp[0]
        twoSelectValue.value = tmp[1]
      } else if (tmp.length == 3) {
        oneSelectValue.value = tmp[0]
        twoSelectValue.value = tmp[1]
        threeSelectValue.value = tmp[2]
      }
    }

    keysOf(data).forEach((e) => {
      // @ts-ignore
      if (e === 'imagesList' || e === 'fileList') return
      // @ts-ignore
      formData.value[e] = data[e] as never
      if (e === 'startDate') {
        formData.value.startDate = data.startDate ? data.startDate.slice(0, 10) : null
      }
      if (e === 'endDate') {
        formData.value.endDate = data.endDate ? data.endDate.slice(0, 10) : null
      }
    })
    if (isUpdate) cascader()

    if (isUpdate || isAdd) {
      // @ts-ignore
      imageFileList.value = data.imagesList.map((e) => ({
        id: e.id,
        name: e.name,
        url: e.path,
        status: 'finished',
        file: {
          remoteId: e.id
        }
      }))
    }
    clueInfo.value = data
  } catch (error) {
    console.error(error)
  }
}

const getDefaultFileList = (e: any) => {
  if (!e) return []
  return (
    e.map((e: any) => {
      return {
        id: e.id,
        name: e.name,
        path: e.path,
        url: e.path,
        remoteId: e.id,
        status: 'success'
      }
    }) ?? []
  )
}

const identifyId = route.query.identifyId as string
const subItemId = route.query.subItemId as string
const queryExpertListLoading = ref(false)
const expertList = ref([])
const queryExpertList = async () => {
  try {
    queryExpertListLoading.value = true
    const [error, res] = await sendRequest<HttpResponse>({
      module: 'item',
      api: 'expertList',
      override: {
        params: {
          identifyId,
          subItemId
        }
      }
    })
    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)
    expertList.value = res.data
  } catch (error) {
    console.error(error)
  } finally {
    queryExpertListLoading.value = false
  }
}
const columns: DataTableColumns<any> = [
  {
    title: '序号',
    key: 'index',
    width: 80,
    align: 'center',
    render: (_, index) => index + 1
  },
  {
    title: '鉴定专家',
    key: 'userName',
    align: 'center'
  },
  {
    title: isTF ? '价值评估' : '价格评估（元）',
    key: isTF ? 'status' : 'identifyValue',
    align: 'center',
    render(e) {
      if (!isTF) return e.identifyValue
      return e.status === 0 ? '真' : e.status === 1 ? '伪' : e.status === 2 ? '无法确定' : ''
    }
  },
  {
    title: '意见',
    key: 'opinion',
    align: 'center'
  }
]

onMounted(() => {
  if (!isDetail && !isUpdate) cascader()
  checkIsDetail()
  if (fromRegisteredDetail) queryExpertList()
})

useRouteParam('id', () => {
  checkIsDetail()
  if (fromRegisteredDetail) queryExpertList()
})

const createLimitRule = (len: number): FormItemRule => {
  return {
    trigger: ['blur', 'input'],
    message: `不能超过${len}字`,
    validator: (_, value) => (value ? value.length <= len : true)
  }
}
</script>

<template>
  <DetailFormProvider :disabled="!isDetail">
    <div class="add-collect">
      <div class="ac-title">物品信息</div>
      <div
        class="ac-card"
        style="padding-bottom: 10rem"
      >
        <NSpace>
          <NForm
            ref="formInst"
            :model="formData"
            label-placement="left"
            :label-width="160"
            require-mark-placement="left"
            :show-require-mark="isDetail ? false : undefined"
            label-align="right"
            :disabled="isDetail"
          >
            <NSpace>
              <NFormItem
                label="类型:"
                path="type"
                :rule="
                  !isDetail
                    ? {
                        required: true,
                        message: '类型必填',
                        key: 'type',
                        validator: () => validatorTypeFormItem()
                      }
                    : undefined
                "
              >
                <NSpace v-if="!isDetail">
                  <!-- !isDetail && (!isUpdate || (isUpdate && !formData.itemTypeName)) -->
                  <NSelect
                    v-model:value="oneSelectValue"
                    :options="(oneSelectOptions as unknown as SelectOption[])"
                    :loading="oneSelectLoading"
                    :disabled="isDetail || oneSelectLoading"
                    style="margin-right: 10rem; width: 350px"
                  />
                  <NSelect
                    v-model:value="twoSelectValue"
                    :options="(twoSelectOptions as unknown as SelectOption[])"
                    :loading="twoSelectLoading"
                    :disabled="isDetail || oneSelectLoading || twoSelectLoading"
                    style="margin-right: 10rem; width: 350px"
                  />
                  <NSelect
                    v-model:value="threeSelectValue"
                    :options="(threeSelectOptions as unknown as SelectOption[])"
                    :disabled="
                      isDetail || oneSelectLoading || twoSelectLoading || threeSelectLoading
                    "
                    :loading="threeSelectLoading"
                    style="width: 350px"
                  />
                </NSpace>

                <NInput
                  v-else
                  disabled
                  :value="formData.itemTypeName"
                  style="width: 1090px"
                />
              </NFormItem>
            </NSpace>
            <NSpace>
              <NFormItem
                label="名称:"
                path="itemName"
                :rule="[
                  {
                    required: true,
                    message: '请输入名称',
                    trigger: ['input', 'blur']
                  },
                  createLimitRule(200)
                ]"
              >
                <NInput
                  v-model:value="formData.itemName"
                  placeholder="输入名称"
                  style="width: 450px;margin-right: 20px;'"
                />
              </NFormItem>
              <NFormItem
                label="数量:"
                path="itemNum"
                :rule="{
                  required: true,
                  trigger: ['blur', 'input'],
                  message: '请输入数量',
                  type: 'number'
                }"
              >
                <NInputNumber
                  v-model:value="formData.itemNum"
                  placeholder="输入数量"
                  style="width: 450px"
                  :show-button="false"
                  :min="0"
                  :max="Number.MAX_SAFE_INTEGER"
                />
              </NFormItem>
            </NSpace>
            <NSpace>
              <NFormItem
                label="规格:"
                path="specifications"
                :rule="createLimitRule(20)"
              >
                <NInput
                  v-model:value="formData.specifications"
                  placeholder="请输入规格"
                  style="width: 450px;margin-right: 20px;'"
                />
              </NFormItem>
              <NFormItem
                label="材质:"
                path="materialQuality"
                :rule="createLimitRule(20)"
              >
                <NInput
                  v-model:value="formData.materialQuality"
                  placeholder="输入材质"
                  style="width: 450px"
                />
              </NFormItem>
            </NSpace>
            <NSpace>
              <NFormItem
                label="装帧:"
                path="binding"
                :rule="createLimitRule(20)"
              >
                <NInput
                  v-model:value="formData.binding"
                  placeholder="请输入装帧"
                  style="width: 450px;margin-right: 20px;'"
                />
              </NFormItem>
              <NFormItem
                label="品相:"
                path="appearance"
                :rule="createLimitRule(20)"
              >
                <NInput
                  v-model:value="formData.appearance"
                  placeholder="请输入品相"
                  style="width: 450px"
                />
              </NFormItem>
            </NSpace>
            <NSpace>
              <NFormItem
                label="年代:"
                path="years"
                :rule="createLimitRule(20)"
              >
                <NInput
                  v-model:value="formData.years"
                  placeholder="请输入年代"
                  style="width: 450px;margin-right: 20px;'"
                />
              </NFormItem>
              <NFormItem
                label="出版社:"
                path="press"
                :rule="createLimitRule(20)"
              >
                <NInput
                  v-model:value="formData.press"
                  placeholder="请输入出版社"
                  style="width: 450px"
                />
              </NFormItem>
            </NSpace>
            <NSpace>
              <NFormItem
                label="语种:"
                path="language"
                :rule="createLimitRule(20)"
              >
                <NInput
                  v-model:value="formData.language"
                  placeholder="请输入语种"
                  style="width: 450px;margin-right: 20px;'"
                />
              </NFormItem>
              <NFormItem
                label="备注:"
                path="notes"
                :rule="createLimitRule(200)"
              >
                <NInput
                  v-model:value="formData.notes"
                  placeholder="请输入备注"
                  style="width: 450px"
                  type="textarea"
                  :autosize="{
                    minRows: 1,
                    maxRows: 5
                  }"
                />
              </NFormItem>
            </NSpace>
            <NFormItem
              label="图片:"
              path="fileIds"
            >
              <FUploader
                v-if="isUpdate || isAdd"
                accept="image/*"
                v-model:fileList="imageFileList"
                :max="3"
              />
              <VAttachments
                v-else
                :attach-list="getDefaultFileList(clueInfo.imagesList)"
              ></VAttachments>
            </NFormItem>
          </NForm>
        </NSpace>

        <template v-if="fromRegisteredDetail">
          <div class="br"></div>

          <div class="ac-title">鉴定详情（{{ isTF ? '价值评估' : '价格评估' }}）</div>
          <NDataTable
            :loading="queryExpertListLoading"
            :data="expertList"
            :columns="columns"
          />
        </template>
      </div>
    </div>
  </DetailFormProvider>
  <FixedAction>
    <div
      class="add-collect-buttons"
      :class="{ start: isDetail }"
    >
      <NButton
        v-if="!isDetail"
        color="#999999"
        ghost
        :disabled="submitLoading"
        @click="routeReplace"
        style="width: 78px; height: 34px"
      >
        取消
      </NButton>
      <NButton
        v-else
        ghost
        :class="{ back: isDetail }"
        @click="routeReplace"
        :style="`width: 78px; color: #5fb17f`"
      >
        <template #icon>
          <NImage
            :src="VBackImg"
            :style="`width: 50rem; height: 50rem`"
            preview-disabled
          ></NImage>
        </template>
        返回
      </NButton>

      <NButton
        v-if="!isDetail"
        color="#5FB17F"
        :disabled="submitLoading"
        :loading="submitLoading"
        @click="handleSubmit"
        style="width: 78px; height: 34px"
      >
        确定
      </NButton>
    </div>
  </FixedAction>
</template>

<style scoped lang="scss">
.add-collect {
  min-height: 100%;
  padding: 15rem 0 130rem;
  background-color: #f0efee;

  .br {
    position: relative;
    width: 100%;
    padding: 30rem 0;

    &::after {
      content: '';
      position: absolute;
      width: 100%;
      top: 50%;
      left: 0;
      border-top: 1px dotted #bc9e70;
      transform: translateY(-50%);
    }
  }

  .ac-card {
    padding: 20rem;
    background-color: #e1e1e1;
  }

  .ac-title {
    font-size: 26rem;
    margin-bottom: 30rem;
    color: #048c5e;
    line-height: 1;
  }
}

.add-collect-buttons {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0 16rem;

  .n-button:not(.back) {
    width: 100rem;
    height: 50rem;
  }

  &.start {
    justify-content: flex-start;
  }
}
</style>
